package org.spring.blog.service.impl;

import com.vladsch.flexmark.ext.jekyll.tag.JekyllTagExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.ext.toc.SimTocExtension;
import com.vladsch.flexmark.ext.toc.TocExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Document;
import com.vladsch.flexmark.util.data.MutableDataSet;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.CommonParams;
import org.jsoup.Jsoup;
import org.spring.blog.base.BaseService;
import org.spring.blog.pojo.Article;
import org.spring.blog.pojo.LRPageList;
import org.spring.blog.pojo.SolrSearchResult;
import org.spring.blog.response.ResponseResult;
import org.spring.blog.response.ResponseState;
import org.spring.blog.service.IArticleService;
import org.spring.blog.service.ISolrService;
import org.spring.blog.utils.LRConstants;
import org.spring.blog.utils.TextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class SolrServiceImpl extends BaseService implements ISolrService {

    @Autowired
    SolrClient solrClient;

    /**
     * 搜索接口
     *
     * @param _keyword    关键词
     * @param _page       页码
     * @param _size       页面大小
     * @param _categoryId 分类id
     * @param _sort       排序方式
     * @return 自定义的返回类型
     */
    @Override
    public ResponseResult doSearch(String _keyword, int _page, int _size, String _categoryId, Integer _sort) {
        // check data
        _page = Math.max(_page, LRConstants.list_default_page_num);
        _size = Math.max(_size, LRConstants.list_min_page_size);

        SolrQuery solrQuery = new SolrQuery();
        // complete data
        // 设置每页的数量
        int start = (_page - 1) * _size;
        solrQuery.setRows(_size)
                .setStart(start);

        // 关键字
        solrQuery.set(CommonParams.DF, "search_item");

        // 条件过滤
        if (TextUtil.isEmpty(_keyword)) {
            solrQuery.set(CommonParams.Q, "*");
        } else {
            solrQuery.set(CommonParams.Q, _keyword);

        }
        // 排序
        if (_sort != null) {
            switch (_sort) {
                case 1:
                    solrQuery.setSort(solr_key_blog_create_time, SolrQuery.ORDER.asc);
                    break;
                case 2:
                    solrQuery.setSort(solr_key_blog_create_time, SolrQuery.ORDER.desc);
                    break;
                case 3:
                    solrQuery.setSort(solr_key_blog_view_count, SolrQuery.ORDER.asc);
                    break;
                case 4:
                    solrQuery.setSort(solr_key_blog_view_count, SolrQuery.ORDER.desc);
                    break;

                default:
                    return ResponseResult.failed(ResponseState.not_support_operation_message, ResponseState.not_support_operation_code);
            }
        }
        // 分类
        if (!TextUtil.isEmpty(_categoryId)) {
            solrQuery.setFilterQueries(solr_key_blog_category_id + ":" + _categoryId);
        }

        // 设置solr 返回的 关键字高亮
        solrQuery.setHighlight(true)
                .addHighlightField(solr_key_blog_title + "," + solr_key_blog_content)
                .setHighlightSimplePre("<font color='red'>")
                .setHighlightSimplePost("</font>")
                .setHighlightFragsize(500);

        // search data
        // 确定自己需要查询的数据 类似 sql 语句
        solrQuery.addField("id,blog_content,blog_create_time,blog_labels,blog_url,blog_title,blog_view_count");

        try {
            // 查询 solr
            QueryResponse result = solrClient.query(solrQuery);

            // 获取高亮的部分
            Map<String, Map<String, List<String>>> highlighting = result.getHighlighting();

            // 将数据转成bean类
            List<SolrSearchResult> resultList = result.getBeans(SolrSearchResult.class);

            // 将需要高亮的部分， 替换成solr 生成的高亮的内容
            for (SolrSearchResult item : resultList) {
                Map<String, List<String>> highLightingMap = highlighting.get(item.getId());

                if (highLightingMap != null) {
                    List<String> blog_content_highLight = highLightingMap.get(solr_key_blog_content);
                    if (blog_content_highLight != null) {
                        item.setBlogContent(blog_content_highLight.get(0));
                    }
                    List<String> blog_title_highLight = highLightingMap.get(solr_key_blog_title);

                    if (blog_title_highLight != null) {
                        item.setBlogTitle(blog_title_highLight.get(0));
                    }
                }
            }

            // check query data
//            System.out.println(resultList);
//            System.out.println(highlighting);

            // complete return data
            long totalCount = result.getResults().getNumFound();

            LRPageList<SolrSearchResult> lrPageList = new LRPageList<>(resultList, _page, totalCount, _size);


            // return data
            return ResponseResult.success().setData(lrPageList);

        } catch (SolrServerException | IOException _e) {
            _e.printStackTrace();
            return ResponseResult.failed();
        }
    }


    /**
     * 添加数据到solr
     *
     * @param _article 文章对象
     */
    public void insertArticle(Article _article) {

        SolrInputDocument solrInputDocument = new SolrInputDocument();

        // complete data
        solrInputDocument.addField(solr_key_blog_id, _article.getId());
        solrInputDocument.addField(solr_key_blog_view_count, _article.getViewCount());
        solrInputDocument.addField(solr_key_blog_title, _article.getTitle());

        // 对文章内容进行处理，去掉标签，提取出纯文本

        // 1. markdown -> html - > 纯文本
        String htmlContent;
        if (IArticleService.constant.db_type_markdown.equals(_article.getType())) {
            MutableDataSet options = new MutableDataSet().set(Parser.EXTENSIONS, Arrays.asList(
                    TablesExtension.create(),
                    JekyllTagExtension.create(),
                    TocExtension.create(),
                    SimTocExtension.create()
            ));

            Parser parser = Parser.builder(options).build();

            HtmlRenderer renderer = HtmlRenderer.builder(options).build();

            Document document = parser.parse(_article.getContent());

            htmlContent = renderer.render(document);

            // 非法操作，数据库的东西除非需要改才能改
            // 不能用来存值
//            _article.setContent(html);
        } else {
            htmlContent = _article.getContent();
        }


        String text = Jsoup.parse(htmlContent).text();

        solrInputDocument.addField(solr_key_blog_content, text);
        solrInputDocument.addField(solr_key_blog_create_time, new Date());
        solrInputDocument.addField(solr_key_blog_labels, _article.getLabel());
        solrInputDocument.addField(solr_key_blog_url, "/admin/article/" + _article.getId());
        solrInputDocument.addField(solr_key_blog_category_id, _article.getCategoryId());

        try {
            // insert data
            solrClient.add(solrInputDocument);
            solrClient.commit();

            System.out.println("success");
        } catch (SolrServerException | IOException _e) {
            _e.printStackTrace();
        }
    }

    /**
     * 删除数据在 solr
     *
     * @param _id 文章id
     */
    @Override
    public void deleteArticleById(String _id) {
        try {
            solrClient.deleteById(_id);
            solrClient.commit();

        } catch (SolrServerException | IOException _e) {
            _e.printStackTrace();
        }
    }

    /**
     * 更新文章内容
     *
     * @param _article 文章对象
     */
    @Override
    public void updateArticle(Article _article) {
        // 跟新solr 和添加是一样的接口
        insertArticle(_article);
    }
}
